package cn.topevery.garden.dal.dao.impl;

import cn.topevery.garden.dal.dao.GreTreeDao;
import cn.topevery.garden.dal.logic.GreFileLogic;
import cn.topevery.garden.dal.logic.GreTreeRecordLogic;
import cn.topevery.garden.entity.po.GreTree;
import cn.topevery.garden.entity.query.GreTreeQuery;
import cn.topevery.garden.entity.vo.GreLandVO;
import cn.topevery.garden.entity.vo.GreTreeRecordVO;
import cn.topevery.garden.entity.vo.GreTreeVO;
import cn.topevery.garden.framework.base.BaseDaoImpl;
import hw.topevery.basis.entity.po.SysUser;
import hw.topevery.basis.runtime.UserRuntime;
import hw.topevery.framework.db.CommandType;
import hw.topevery.framework.db.DbCommand;
import hw.topevery.framework.db.entity.DataPager;
import hw.topevery.framework.db.entity.SqlQueryMate;
import hw.topevery.framework.db.entity.SqlUpdateMate;
import hw.topevery.framework.db.enums.ScriptConditionEnum;
import hw.topevery.framework.dto.PointDto;
import hw.topevery.framework.entity.DbCsp;
import hw.topevery.framework.entity.KeyValue;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 行道树
 *
 * @author code-generate
 * @date 2022-01-05
 */
@Repository
public class GreTreeDaoImpl extends BaseDaoImpl<GreTree> implements GreTreeDao {
    @Autowired
    private GreTreeRecordLogic greTreeRecordLogic;
    @Autowired
    private GreFileLogic greFileLogic;

    @Override
    public <P extends DbCsp> List<GreTree> getSearch(P para) {
        return null;
    }


    @Override
    public DataPager<GreTreeVO> listPage(GreTreeQuery query) {
        String table = "t_gre_tree tgt";

        String columns = "tgt.*";

        int pageIndex = query.pageIndex - 1;
        int pageSize = query.pageSize;

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns).setOrderBy("tgt.c_id desc");
        StringBuilder sqlBuilder = new StringBuilder();
        if(ObjectUtils.isNotEmpty(query.getMapRangesPoints())){
            sqlBuilder.append(" ST_Distance(c_map_ranges,ST_GeomFromText('MULTIPOLYGON( ((");

            for(int j=0;j<query.getMapRangesPoints().size();j++){
                PointDto point = query.getMapRangesPoints().get(j);
                if(j>0){
                    sqlBuilder.append(",");
                }
                sqlBuilder.append(point.getLng()+ " "+ point.getLat());
            }
            sqlBuilder.append(")))') )");
        }
        sqlQueryMate
                .where(true, "tgt.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(ObjectUtils.isNotEmpty(query.getMapRangesPoints()), sqlBuilder.toString(), ScriptConditionEnum.Eq, 0)
                ;
        return getDataPager(sqlQueryMate, pageSize, pageIndex, GreTreeVO.class);
    }

    @Override
    public GreTree getEntityByColumn(String key, String value) {
        KeyValue<String> map = new KeyValue<>();
        map.key = key;
        map.value = value;
        return getEntityByColumnEqValue(map);
    }

    @Override
    public DataPager<GreTreeVO> getList(GreTreeQuery query) {
        String table = "t_gre_tree tgt";

        String columns = "tgt.*";

        int pageIndex = query.pageIndex - 1;
        int pageSize = query.pageSize;

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns).setOrderBy("tgt.c_id asc");
        sqlQueryMate
                .where(true, "tgt.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(StringUtils.isNotBlank(query.getCode()), "tgt.c_code", ScriptConditionEnum.Like, query.getCode())
                .where(StringUtils.isNotBlank(query.getName()), "tgt.c_name", ScriptConditionEnum.Like, query.getName())
                .where(StringUtils.isNotBlank(query.getTreeKind()), "tgt.c_tree_kind", ScriptConditionEnum.Like, query.getTreeKind())
                .where(StringUtils.isNoneBlank(query.beginDate) && StringUtils.isNoneBlank(query.endDate), "c_date", ScriptConditionEnum.GreaterThanEq, query.beginDate)
                .where(StringUtils.isNoneBlank(query.beginDate) && StringUtils.isNoneBlank(query.endDate), "c_date", ScriptConditionEnum.LessThanEq, query.endDate)
                .where(StringUtils.isNoneBlank(query.getAloneLoad()), "c_alone_load", ScriptConditionEnum.Like, query.getAloneLoad())
                .where(StringUtils.isNoneBlank(query.getDistractId()), "c_distract_id", ScriptConditionEnum.Like, query.getDistractId())
                .where(StringUtils.isNoneBlank(query.getKeyWord()), "concat(ifnull(c_code, ''), ifnull(c_name, ''), ifnull(c_distract_name, ''), ifnull(c_alone_load, ''))",
                        ScriptConditionEnum.Like, query.getKeyWord());

        return getDataPager(sqlQueryMate, pageSize, pageIndex, GreTreeVO.class);
    }

    @Override
    public DataPager<GreTreeRecordVO> getRecordList(GreTreeQuery query) {
        String table = "t_gre_tree_record t\n" +
                "JOIN t_sys_user tsu ON t.c_db_create_id = tsu.c_id";
        String columns = "t.*, tsu.c_user_name `c_db_create_name`";
        int pageIndex = query.pageIndex - 1;
        int pageSize = query.pageSize;
        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns).setOrderBy("c_db_create_date DESC");
        sqlQueryMate.where(true, "t.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(query.getTreeIntId() != null, "c_tree_int_id", ScriptConditionEnum.Eq, query.getTreeIntId());
        return getDataPager(sqlQueryMate, pageSize, pageIndex, GreTreeRecordVO.class);
    }

    @Override
    public void update(GreTree greTree, Integer userId) {
        SysUser user = UserRuntime.getSysUser();
        greTree.setCreateTime(LocalDateTime.now());
        update(user.userId, greTree);
        Integer id = greTreeRecordLogic.insert(greTree);
        greFileLogic.deleteByMainId(greTree.getId(), userId);
        if (greTree.getFileList() != null && !greTree.getFileList().isEmpty()) {
            greFileLogic.insertList(greTree.getFileList().stream().peek(temp -> {
                temp.setDataType(2);
                temp.setCreateTime(LocalDateTime.now());
                temp.setCreateId(user.userId);
                temp.setMainId(greTree.getId());
                temp.setMainRecordId(id);
                temp.setDbStatus(false);
            }).collect(Collectors.toList()));
        }
    }

    @Override
    public void insert(GreTree greTree, Integer userId) {
        SysUser user = UserRuntime.getSysUser();
        greTree.setCreateTime(LocalDateTime.now());
        greTree.setCreateId(user.userId);
        insert(user.userId, greTree);
        Integer id = greTreeRecordLogic.insert(greTree);
        if (greTree.getFileList() != null && !greTree.getFileList().isEmpty()) {
            greFileLogic.insertList(greTree.getFileList().stream().peek(temp -> {
                temp.setDataType(2);
                temp.setCreateTime(LocalDateTime.now());
                temp.setCreateId(user.userId);
                temp.setMainId(greTree.getId());
                temp.setMainRecordId(id);
                temp.setDbStatus(false);
            }).collect(Collectors.toList()));
        }
    }

    @Override
    public void deleteByIds(List<String> ids) {
        SqlUpdateMate sqlUpdateMate = new SqlUpdateMate("t_gre_tree");
        sqlUpdateMate.setColumnValue(true, "c_db_status", 1)
                .where(true, "c_id", ScriptConditionEnum.In, ids);
        run(sqlUpdateMate.getSql(), CommandType.Text, dbCommand -> {
            sqlUpdateMate.getParameters().forEach(dbCommand::addParameter);
            dbCommand.executeNonQuery();
        });
    }

    @Override
    public void deleteById(Integer id) {
        SqlUpdateMate sqlUpdateMate = new SqlUpdateMate("t_gre_tree");
        sqlUpdateMate.setColumnValue(true, "c_db_status", 1)
                .where(true, "c_id", ScriptConditionEnum.Eq, id);
        run(sqlUpdateMate.getSql(), CommandType.Text, dbCommand -> {
            sqlUpdateMate.getParameters().forEach(dbCommand::addParameter);
            dbCommand.executeNonQuery();
        });
    }

    @Override
    public List<Map<String, Object>> getAllTreeForMap(String type) {
        SqlQueryMate sqlQueryMate = new SqlQueryMate("t_gre_tree").setColumns("c_tree_id,\n" +
                "        c_code,\n" +
                "        c_name,\n" +
                "        IFNULL(c_lng,0) c_lng,\n" +
                "        IFNULL(c_lat,0) c_lat");
        sqlQueryMate.where(true, "c_db_status", ScriptConditionEnum.Eq, 0)
                .where(true, "c_lng", ScriptConditionEnum.NotEq, null)
                .where(StringUtils.isNotBlank(type), "c_type", ScriptConditionEnum.Eq, type);
        return getMap(sqlQueryMate);
    }

    @Override
    public void insertSql(GreTree greTree) {
        String sql = "insert into t_gre_tree(\n" +
                "    c_tree_id,\n" +
                "    c_code,\n" +
                "    c_name,\n" +
                "    c_tree_height,\n" +
                "    c_type,\n" +
                "    c_type_name,\n" +
                "    c_lng,\n" +
                "    c_lat,\n" +
                "    c_tree_width,\n" +
                "    c_growth,\n" +
                "    c_address,\n" +
                "    c_alone_load,\n" +
                "    c_db_create_id,\n" +
                "    c_db_create_date,\n" +
                "    c_db_status,\n" +
                "    c_distract_id,\n" +
                "    c_distract_name\n" +
                "    )\n" +
                "    SELECT\n" +
                greTree.getTreeId() + "    ,\n" +
                greTree.getCode() + "    ,\n" +
                greTree.getName() + "    ,\n" +
                greTree.getTreeHeight() + "    ,\n" +
                greTree.getType() + "    ,\n" +
                greTree.getTypeName() + "    ,\n" +
                greTree.getLng() + "    ,\n" +
                greTree.getLat() + "    ,\n" +
                greTree.getTreeWidth() + "    ,\n" +
                greTree.getGrowth() + "    ,\n" +
                greTree.getAddress() + "    ,\n" +
                greTree.getAloneLoad() + "    ,\n" +
                greTree.getCreateId() + "    ,\n" +
                greTree.getCreateTime() + "    ,\n" +
                greTree.getDbStatus() + "    ,\n" +
                "    t.c_map_id,\n" +
                "    t.c_name\n" +
                "    from t_sys_map t\n" +
                "    WHERE\n" +
                "    t.c_name = " + greTree.getDistractName();
        run(sql, CommandType.Text, DbCommand::executeNonQuery);
    }

    public Map getCount(String name, String sectionId) {
        String table = "t_gre_tree tp";

        String columns = "count(1) value,'行道树' as name";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(name != null, "tp.c_tree_kind", ScriptConditionEnum.Eq, name)
                .where(StringUtils.isNotBlank(sectionId), "tp.c_obj_name", ScriptConditionEnum.Eq, sectionId)

        ;
        return getOneMap(sqlQueryMate);

    }

    public List<GreTreeVO> getTypeList(String sectionId) {
        String table = "t_gre_tree tp";

        String columns = "distinct tp.c_tree_kind c_type, c_tree_kind c_type_name ";

        SqlQueryMate sqlQueryMate = new SqlQueryMate(table).setColumns(columns);
        sqlQueryMate
                .where(true, "tp.c_db_status", ScriptConditionEnum.Eq, 0)
                .where(StringUtils.isNotBlank(sectionId), "tp.c_obj_name", ScriptConditionEnum.Eq, sectionId)
        ;

        List<GreTreeVO> list = selectList(sqlQueryMate, GreTreeVO.class);
        for (GreTreeVO greTreeVO : list) {
            if (StringUtils.isNotEmpty(greTreeVO.getType())) {
                Map map = getCount(greTreeVO.getType(), null);
                greTreeVO.setTotalNumber(String.valueOf(map.get("value")));
            }
        }
        return list;
    }

}
